/*
 * Amkai Enterprise Solution (AES.) 
 * Copyright 2004 by Amkai(TM), Inc.
 * www.amkai.com
 * 
 * Project: webservice
 * Package: com.amkai.aes.webservice.binary.objecthandler
 * File: PassportManagerHandler.java
 * Created: Feb 1, 2006 2:14:52 PM
 * Author: johnny 
 * 
 */
package com.amkai.aes.webservice.binary.objecthandler;

import java.io.Serializable;
import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.Vector;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.Transaction;

import com.amkai.aes.aescommon.CommonSettings;
import com.amkai.aes.aescommon.factory.RADBeanFactory;
import com.amkai.aes.aescommon.service.binary.job.PassportManagerJob;
import com.amkai.aes.aescommon.service.result.PassportManagerResult;
import com.amkai.aes.generatedbeans.organization.BusinessGroup;
import com.amkai.aes.generatedbeans.organization.Department;
import com.amkai.aes.generatedbeans.passport.ACLoginSupport;
import com.amkai.aes.generatedbeans.passport.DepartmentSpecificRole;
import com.amkai.aes.generatedbeans.passport.Passport;
import com.amkai.aes.generatedbeans.passport.PassportBGAssociation;
import com.amkai.aes.generatedbeans.registration.BgSpecificProperties;
import com.amkai.aes.generatedbeans.registration.Person;
import com.amkai.aes.generatedbeans.security.PasswordHistory;
import com.amkai.aes.generatedbeans.security.Role;
import com.amkai.aes.generatedbeans.tree.Node;
import com.amkai.aes.generatedbeans.tree.NodeKind;
import com.amkai.aes.generatedmodels.administration.passport.PassportDomain;
import com.amkai.aes.server.hibernate.managment.PassportManager;
import com.amkai.aes.server.manager.PassportSecurityManager;
import com.amkai.aes.server.manager.passport.ServerPassportManager;
import com.amkai.aes.server.preference.PassportAndOrganizationMaps;
import com.amkai.aes.webservice.binary.JobObjectHandler;
import com.amkai.common.extensions.hibernate.config.SiteManager;
import com.amkai.common.extensions.hibernate.config.manager.SessionManager;
import com.amkai.extensions.messaging.MessagingProvider;
import com.amkai.rad.designerbase.beans.ChangedKind;
import com.amkai.rad.designerbase.beans.RADBean;
import com.sun.corba.se.pept.encoding.InputObject;

/**
 * PassportManagerHandler
 * @author johnny
 * Description:
 *
 */
public class PassportManagerHandler implements JobObjectHandler<PassportManagerJob, Serializable, PassportManagerResult> {

	private static final Log log = LogFactory.getLog(PassportManagerHandler.class);

	
	/** 
	 * Overriden method
	 * @param job
	 * @param object
	 * @return
	 * @throws Exception
	 * @see com.amkai.aes.webservice.binary.JobObjectHandler#process(E, InputObject)
	 * 
	 */
	@SuppressWarnings({"rawtypes", "unchecked"})
	public PassportManagerResult process(PassportManagerJob job, Serializable object) throws Exception {
		SessionManager sm = SiteManager.Start();
		if (sm == null) {
			sm = SiteManager.Start();
		}
		PassportManager manager = new PassportManager(sm);
		PassportManagerResult result = new PassportManagerResult();
		Transaction tx = null;
		try {
			// KKORNEL: AES-4507
			sm.openSession(/*LogInterceptor.newInstance(null, null, sm.getFactory().getSessionFactory())*/);
			// KKORNEL: AES-16950
			//switch (job.getMode()) {
			switch (job.getJobKind()) {
			case /*PassportManagerJob.*/GETPASSPORTROLES:
				if (job.getPassportId() != null) {
					result.setRoles(manager.getPassportRoles(job.getPassportId()));
				}
				break;
			case /*PassportManagerJob.*/GETROLES: 
				String query = "SELECT r FROM Role r";
//				String query = "SELECT r FROM Role r LEFT JOIN FETCH r.baseOrganization bo LEFT JOIN FETCH bo.parent bg";
				result.setRoles(sm.execute(query).list());
				//#12575
//				String query = "SELECT r FROM Role r LEFT JOIN FETCH r.baseOrganization bo LEFT JOIN FETCH bo.parent bg WHERE bg.id = :bgId";
//				BusinessGroup bg = (BusinessGroup)job.getDepartment().getParent();
//				List<Role> roles = sm.execute(query).setLong("bgId", bg.getId()).list();
//				result.setRoles(roles);
				break;
			case /*PassportManagerJob.*/START:
				List<Passport> pass = manager.getPassports(-1); 
				for (Passport p : pass) {
					// KKORNEL: AES-16950
					loadPassport(sm, p, job.getModuleDepartment().getId());
				}
				result.setPassports(pass);
				break;
			case /*PassportManagerJob.*/UPDATEROLESADD:
				if (object != null && object instanceof Vector) {
					Vector vector = (Vector)object;
					tx = sm.openTransaction();
					manager.updateRoles(job.getPassportId(), vector/*, PassportManagerJob.UPDATEROLESADD*/);
					sm.commitTransaction();
				}
				else {
//					FIXME add message to error messages.
					throw new Exception("Not give roles!!!!!");
				}
				break;
			case /*PassportManagerJob.*/UPDATEROLESREMOVE:
				if (object != null && object instanceof Vector) {
					Vector vector = (Vector)object;
					tx = sm.openTransaction();
					manager.updateRoles(job.getPassportId(), vector/*, PassportManagerJob.UPDATEROLESREMOVE*/);
					sm.commitTransaction();
				}
				else {
//					FIXME add message to error messages.
					throw new Exception("Not give roles!!!!!");
				}
				break;
			case /*PassportManagerJob.*/SAVE: {
				sm.openTransaction();
				Passport passport = ((PassportDomain)object).getPassport();
				BgSpecificProperties bgSpecificProperties = ((PassportDomain)object).getBgSpecificProperties();
			 	// KKORNEL: AES-5818 - If this is commented then AC Login supports can not be saved
				boolean idWasEmpty = false;
				if (passport.getId() == null) {
					idWasEmpty = true;
				}
				// KKORNEL: AES-6900 - Is the passport name is duplicated ?
				if (passport.getName() != null) {
					List<Long> passportIdWithThisName = sm.execute("SELECT id FROM Passport WHERE name = :name").setString("name", passport.getName()).list();
					if ((passportIdWithThisName != null) && ((passportIdWithThisName.size() > 2) || (passportIdWithThisName.size() == 1) && 
							(idWasEmpty || passportIdWithThisName.get(0).longValue() != passport.getId().longValue()))) {
						throw new Exception("Duplicated passport name");
					}
				}
				// KKORNEL: AES-11270 - The new unsaved passport can not have failed login.
				// This was thrown an exception.
				if (passport.isActive() && (passport.getChangedKind() != ChangedKind.CREATED)){
					PassportSecurityManager.ClearFailedLogins(passport, "");
				}
				
				sm.saveRAD(passport);
				sm.saveRAD(bgSpecificProperties);
				
				//GYAND - AES-12467 
				if(job.passwordChanged) {
					System.err.println("PASSWORD CHANGED !!!!");
					PasswordHistory ph = RADBeanFactory.getInstance().createBean(PasswordHistory.class);
					ph.setDate(new Date());
					ph.setPassport(passport);
					ph.setOldPassword(passport.getPassword());					
					sm.saveRAD(ph);				
				}
				//GYAND - AES-12467 
				//GYAND - AES-16903
				MessagingProvider.initPassport(passport, sm);
				//GYAND - AES-16903 
				 // KKORNEL: AES-5818 - If this is commented then AC Login supports can not be saved
				if (/*passport.getId() == null*/ idWasEmpty) {
					//Long newid = manager.saveNewPassport(passport);
					result.setNewPassportId(passport.getId() /*newid*/);
				}
				else {
//					sm.updateV(passport);
					result.setNewPassportId(null);
				}
				sm.saveRAD(passport.getPerson());
				for(DepartmentSpecificRole role : passport.getDepartmentSpecificRoles()){
					sm.saveRAD(role);
				}
				//#12575
				BusinessGroup businessGroup = (BusinessGroup) job.getModuleDepartment().getParent();
				// is passport exists in this BusinessGroup?
				if (!com.amkai.aes.aescommon.passport.PassportManager.isPassportActiveInBusinessGroup(passport, businessGroup)) {
					// create association
					PassportBGAssociation passportBGAssociation = RADBeanFactory.getInstance().createBean(PassportBGAssociation.class);
					passportBGAssociation.setPassport(passport);
					passportBGAssociation.setBusinessGroup(businessGroup);
					sm.saveRAD(passportBGAssociation);
				}
				// KKORNEL: AES-17954
				if (job.getUserGroupPreference() != null) {
					ServerPassportManager.setUserGroupPreferenceForPassport(sm, passport.getId(), job.getUserGroupPreference().getId());
				}
				if (job.getWorkGroupPreference() != null) {
					ServerPassportManager.setWorkGroupPreferenceForPassport(sm, passport.getId(), job.getWorkGroupPreference().getId());
				}
				sm.commitTransaction();
				
				PassportManager.updatePassportForMessaging(sm, passport);
	            // KKORNEL: AES-18018
	            //if (CommonSettings.USE_PREFERENCES) {
	            	PassportAndOrganizationMaps.constructPassportIdToUserGroupIdMap(sm);
	            	PassportAndOrganizationMaps.constructPassportIdToWorkGroupIdMap(sm);
	            //}
				break;
			}
			case /*PassportManagerJob.*/UPDATEACLOGINADD:
				Vector supports = (Vector) object;
				//tx = sm.openTransaction();
				for (Object object2 : supports) {
					sm.saveRADInTransaction((RADBean) object2);
				}
				//sm.commitTransaction();
				break;
			case /*PassportManagerJob.*/UPDATEACLOGINREMOVE:
				Vector sids = (Vector) object;
				List<ACLoginSupport> entities = sm.execute("SELECT a FROM ACLoginSupport a WHERE a.id IN (:sids)")
													.setParameterList("sids", sids)
													.list();
				for (ACLoginSupport support : entities) {
					tx = sm.openTransaction();
					sm.delete(support);
					sm.commitTransaction();
				}
				break;
			// KKORNEL: AES-16950
			case LOAD_PASSPORT: {
				Passport loadedPassport = sm.get(Passport.class, job.getPassportId());
				loadPassport(sm, loadedPassport, job.getModuleDepartment().getId());
				result.setPassport(loadedPassport);
				// KKORNEL: AES-17954
				result.setUserGroupPreference(ServerPassportManager.getUserGroupPreferenceForPassport(sm, loadedPassport.getId(), job.getModuleDepartment().getId()));
				result.setWorkGroupPreference(ServerPassportManager.getWorkGroupPreferenceForPassport(sm, loadedPassport.getId(), job.getModuleDepartment().getParent().getId()));
				break;
			}
				
			}
		}
		catch (Exception e) {
			log.error("",e);
			if (tx != null) {
				sm.rollbackTransaction();
			}
			throw e;
		    //GYAND - AES-16900 
		} catch (Throwable e) {
			log.error("",e);
			if (tx != null) {
				sm.rollbackTransaction();
			}
			throw new Exception(e);
		    //GYAND - AES-16900 
		}
		finally {
			sm.closeSession();
		}
		return result;
	}


	// KKORNEL: AES-16950 - job parameter has been changed to departmentId
	private void loadPersonBgSpecificProperties(SessionManager sm, Long departmentId, Person person) throws Exception {
		Department department = sm.get(Department.class, departmentId);
		Node bgNode = department.getParent();
		if (bgNode.getKind().equals(NodeKind.BUSINESS_GROUP)){
			
			BusinessGroup bg = (BusinessGroup)sm.get(BusinessGroup.class, bgNode.getId());
			loadBgSpecificProperties(bg, person);			
		}else{
			log.error("Department parent is not a Business Group!!! BE name: " + department.getName() + " BE id : " + department.getId());
			throw new RuntimeException("Department parent is not a Business Group!!! BE name: " + department.getName() + " BE id : " + department.getId());
		}
		
	}


	private void loadBgSpecificProperties(BusinessGroup bg, Person person) {
		for(BgSpecificProperties bgp : person.getBgSpecificPropertieses()){
			if (bgp.getBusinessGroup().getId().equals(bg.getId())){
				bgp.isIncludeMPI();
			}
		}
		
	}

	// KKORNEL: AES-16950
	private void loadPassport(SessionManager sm, Passport p, Long departmentId) throws Exception {
		if (p.getPerson() != null) {
			p.getPerson().getFirstName();
			p.getPerson().getLastName();
			p.getPerson().getDateOfBirth();
			p.getPerson().getMiddleInitial();
			p.getPerson().getIsMale();
			loadPersonBgSpecificProperties(sm, departmentId, p.getPerson());
		}
		for(DepartmentSpecificRole dsr : p.getDepartmentSpecificRoles()) {
			if(dsr.getDepartment() != null){
				dsr.getDepartment().getId();
				dsr.getDepartment().getName();
			}
			Role r = dsr.getRole();
			if(r != null) {
				r.getId();
				r.getShortName();
				r.getName();
			}
		}
		//#12575
		Set<PassportBGAssociation> passportBGAssociations = p.getPassportBGAssociations();
		if (passportBGAssociations != null) {
			for (PassportBGAssociation passportBGAssociation : passportBGAssociations) {
				Passport passport = passportBGAssociation.getPassport();
				if (passport != null) {
					Person person = passport.getPerson();
					if (person != null) {
						person.getFirstName();
						person.getLastName();
						person.getDateOfBirth();
						person.getMiddleInitial();
						person.getIsMale();
					}
				}
				BusinessGroup businessGroup = passportBGAssociation.getBusinessGroup();
				if (businessGroup != null) {
					businessGroup.getName();
					businessGroup.getKind();
					businessGroup.getLevel();
				}
			}
		}
		if (p.getSupervisor() != null) {
			p.getSupervisor().getName();
		}
		
	}
	
}
